using System;
using System.Threading.Tasks;

namespace AsyncPowerCalculationEnhanced
{
    class Program
    {
        static async Task Main(string[] args)
        {
            Console.WriteLine("异步计算表达式: a^58 + b^50");
            Console.WriteLine("使用优化的大指数计算方法");
            Console.WriteLine("==================================\n");

            try
            {
                // 获取用户输入的a和b值
                double a = GetInputValue("a");
                double b = GetInputValue("b");

                Console.WriteLine($"\n开始计算: {a}^58 + {b}^50");
                
                // 方法1: 使用Math.Pow进行异步计算
                await CalculateUsingMathPow(a, b);
                
                // 方法2: 使用优化的快速幂算法进行异步计算
                await CalculateUsingFastPower(a, b);

            }
            catch (Exception ex)
            {
                Console.WriteLine($"发生错误: {ex.Message}");
                Console.WriteLine(ex.StackTrace);
            }

            Console.WriteLine("\n按任意键退出...");
            Console.ReadKey();
        }

        /// <summary>
        /// 使用Math.Pow进行异步计算
        /// </summary>
        private static async Task CalculateUsingMathPow(double a, double b)
        {
            Console.WriteLine("\n方法1: 使用Math.Pow进行计算");
            DateTime startTime = DateTime.Now;

            // 并行计算两个幂运算
            Task<double> taskA = Task.Run(() => Math.Pow(a, 58));
            Task<double> taskB = Task.Run(() => Math.Pow(b, 50));

            // 等待两个计算完成
            await Task.WhenAll(taskA, taskB);

            // 获取结果
            double resultA = taskA.Result;
            double resultB = taskB.Result;
            double sum = resultA + resultB;

            DateTime endTime = DateTime.Now;
            TimeSpan duration = endTime - startTime;

            Console.WriteLine($"{a}^58 = {resultA}");
            Console.WriteLine($"{b}^50 = {resultB}");
            Console.WriteLine($"{a}^58 + {b}^50 = {sum}");
            Console.WriteLine($"计算耗时: {duration.TotalMilliseconds:F4} 毫秒");
        }

        /// <summary>
        /// 使用优化的快速幂算法进行异步计算
        /// </summary>
        private static async Task CalculateUsingFastPower(double a, double b)
        {
            Console.WriteLine("\n方法2: 使用快速幂算法进行计算");
            DateTime startTime = DateTime.Now;

            // 并行计算两个幂运算
            Task<double> taskA = Task.Run(() => FastPower(a, 58));
            Task<double> taskB = Task.Run(() => FastPower(b, 50));

            // 等待所有计算完成
            double[] results = await Task.WhenAll(taskA, taskB);

            double sum = results[0] + results[1];

            DateTime endTime = DateTime.Now;
            TimeSpan duration = endTime - startTime;

            Console.WriteLine($"{a}^58 = {results[0]}");
            Console.WriteLine($"{b}^50 = {results[1]}");
            Console.WriteLine($"{a}^58 + {b}^50 = {sum}");
            Console.WriteLine($"计算耗时: {duration.TotalMilliseconds:F4} 毫秒");
        }

        /// <summary>
        /// 快速幂算法 - 更高效地计算幂运算
        /// </summary>
        /// <param name="baseValue">底数</param>
        /// <param name="exponent">指数</param>
        /// <returns>计算结果</returns>
        private static double FastPower(double baseValue, int exponent)
        {
            if (exponent == 0)
                return 1;
            if (exponent == 1)
                return baseValue;

            double result = 1.0;
            double currentBase = baseValue;

            // 使用二进制分解指数，减少乘法次数
            while (exponent > 0)
            {                
                // 如果当前二进制位为1，则乘上当前的底数
                if (exponent % 2 == 1)
                {                    
                    result *= currentBase;
                }
                
                // 底数自乘，准备下一位
                currentBase *= currentBase;
                
                // 指数右移一位（相当于除以2）
                exponent /= 2;
            }

            return result;
        }

        /// <summary>
        /// 获取用户输入的数值，并验证是否在1到10之间
        /// </summary>
        private static double GetInputValue(string variableName)
        {            
            while (true)
            {                
                Console.Write($"请输入{variableName}的值 (1 < {variableName} < 10): ");
                string input = Console.ReadLine();
                
                if (double.TryParse(input, out double value))
                {                    
                    if (value > 1 && value < 10)
                    {                        
                        return value;
                    }                    
                    else                    
                    {                        
                        Console.WriteLine($"错误：{variableName}的值必须大于1且小于10，请重新输入。");
                    }                
                }
                else                
                {                    
                    Console.WriteLine("错误：请输入有效的数字。");                
                }            
        }
    }
}